package com.xzl.authserver.service.impl;

import com.xzl.authserver.domain.User;
import com.xzl.authserver.domain.repository.UserRepository;
import com.xzl.authserver.security.JwtUserFactory;
import com.xzl.authserver.service.AuthService;
import com.xzl.boilerplate.common.dto.ResultResponse;
import com.xzl.boilerplate.common.dto.UserDTO;
import com.xzl.boilerplate.common.dto.exception.BizCode;
import com.xzl.boilerplate.common.dto.exception.BizException;
import com.xzl.boilerplate.common.security.JwtTokenUtil;
import com.xzl.boilerplate.common.security.JwtUser;
import com.xzl.boilerplate.common.utils.RestTemplateUtil;
import com.xzl.boilerplate.common.utils.UrlUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static java.util.Arrays.asList;

@Service
public class AuthServiceImpl implements AuthService {

    private UserDetailsService userDetailsService;
    private JwtTokenUtil jwtTokenUtil;
    private UserRepository userRepository;
    @Autowired
    private RestTemplateUtil restTemplateUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Value("${domain}")
    public String domain;

    @Autowired
    public AuthServiceImpl(
            UserDetailsService userDetailsService,
            JwtTokenUtil jwtTokenUtil,
            UserRepository userRepository) {
        this.userDetailsService = userDetailsService;
        this.jwtTokenUtil = jwtTokenUtil;
        this.userRepository = userRepository;
    }

    @Override
    public User register(User userToAdd) {
        final String username = userToAdd.getUsername();
        if (userRepository.findByUsername(username) != null) {
            return null;
        }
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        final String rawPassword = userToAdd.getPassword();
        userToAdd.setPassword(encoder.encode(rawPassword));
        userToAdd.setLastPasswordResetDate(new Date());
        userToAdd.setRolesArray(asList("ROLE_USER"));
        return userRepository.save(userToAdd);
    }

    @Override
    public Map login(String username, String password) throws BizException, IOException {
        Map body = new HashMap();
        body.put("userCode", username);
        body.put("userPwsd", password);
        ResultResponse<UserDTO> resultResponse = restTemplateUtil.getBasePlatform(UserDTO.class, domain+UrlUtil.WEIBAO_LOGIN, HttpMethod.POST,
                body, UrlUtil.headers);
//        final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (resultResponse.getCode()!=0)
            throw new BizException(BizCode.USER_AUTH_REQUEST);
        JwtUser userDetails = JwtUserFactory.create(resultResponse.getData());
        final String token = jwtTokenUtil.generateToken(userDetails);

        Map map = new HashMap();
        map.put("token", token);
        map.put("roles", resultResponse.getData().getRoles());
        return map;
    }

    @Override
    public String refresh(String oldToken) {
        final String token = oldToken.substring(tokenHead.length());
//        JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username);
//        if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) {
            return jwtTokenUtil.refreshToken(token);
//        }
    }
}
